#include <iostream>
#include <iomanip>
#include <stack>

using namespace std;

#define MAX_ROWS        10
#define MAX_PEOPLE      30

struct position_coord
{
    unsigned int row;
    unsigned int col;
};

struct state_node
{
    position_coord pos;
    unsigned int   min_height;
    unsigned int   current_height;
};

typedef stack<state_node> STACK;

bool get_next_coord(const position_coord&   coord_in,
                    position_coord&         coord_out,
                    const unsigned int*     rows)
{
    bool ret = false;

    coord_out = coord_in;
    if (++coord_out.col < rows[coord_in.row])
    {
        ret = true;
    }
    else if ((++coord_out.row < MAX_ROWS) && rows[coord_out.row] > 0)
    {
        coord_out.col = 0;
        ret = true;
    }

    return ret;
}

bool choose_people(state_node&          node,
                   const bool*          is_people_used,
                   const unsigned int   occupied_state[][MAX_PEOPLE+1])
{
    bool ret = false;

    for(unsigned int i = node.current_height; i <= node.min_height; i++)
    {
        if (!is_people_used[i] &&
            (i > occupied_state[node.pos.row+1][node.pos.col]) &&
            (i > occupied_state[node.pos.row][node.pos.col+1]))
        {
            node.current_height = i;
            ret = true;
            break;
        }
    }

    return ret;
}

int main(void)
{
    unsigned int num_of_row;

    while((cin>>num_of_row) && (num_of_row != 0))
    {
        unsigned int i, j, k;
        unsigned int total = 0;
        unsigned int count = 0;
        unsigned int rows[MAX_ROWS] = {0};
        unsigned int weight[MAX_ROWS][MAX_PEOPLE] = {{0}};
        unsigned int occupied_state[MAX_ROWS+1][MAX_PEOPLE+1] = {{0}};
        bool         is_people_used[MAX_PEOPLE+1] = {0};
        STACK        node_stack;

        cout<<"number of row: "<<num_of_row<<endl;

        for(i = 0; i < num_of_row; i++)
        {
            cin>>rows[i];
            cout<<rows[i]<<" ";
            total += rows[i];
        }

        cout<<endl<<"Total: "<<total<<endl;
        cout<<"Weight: "<<endl;

        for(i = 0; i < num_of_row; i++)
        {
            for(j = 0; j < rows[i]; j++)
            {
                for(k = i; k < num_of_row; k++)
                {
                    if (j < rows[k])
                        weight[i][j] += rows[k] - j;
                }
                weight[i][j] -= 1;
                cout<<setw(2)<<weight[i][j]<<", ";
            }
            cout<<endl;
        }

        state_node node;

        node.pos.row = 0;
        node.pos.col = 0;
        node.min_height = total - weight[0][0];
        node.current_height = 0;
        node_stack.push(node);

        while(!node_stack.empty())
        {
            if (node_stack.size() == total)
            {
                node_stack.top().current_height++;
                if (choose_people(node_stack.top(), is_people_used, occupied_state))
                {
                    count++;
                    occupied_state[node_stack.top().pos.row+1][node_stack.top().pos.col+1] = node_stack.top().current_height;
//                    cout<<"Arrange: "<<endl;
//                    for(i = 0; i < num_of_row; i++)
//                    {
//                        for(j = 0; j < rows[i]; j++)
//                        {
//                            cout<<occupied_state[i+1][j+1]<<", ";
//                        }
//                        cout<<endl;
//                    }
                }
                node_stack.pop();
            }
            else
            {
                is_people_used[node_stack.top().current_height++] = false;

                if (choose_people(node_stack.top(), is_people_used, occupied_state))
                {
                    is_people_used[node_stack.top().current_height] = true;
                    occupied_state[node_stack.top().pos.row+1][node_stack.top().pos.col+1] = node_stack.top().current_height;
                    if (get_next_coord(node_stack.top().pos, node.pos, rows))
                    {
                        node.min_height = total - weight[node.pos.row][node.pos.col];
                        node.current_height = 0;
                        node_stack.push(node);
                    }
                    else
                    {
                        cout<<"stack: should not get to here!"<<endl;
                    }
                }
                else
                {
                    node_stack.pop();
                }
            }
        }

        cout<<count<<endl;

        cout<<"=================================="<<endl;
    }

    return 0;
}
